package com.org.oracle.strategy.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.org.oracle.enums.ResponseCodeEnum;
import com.org.oracle.exception.CustomException;
import com.org.oracle.helper.ImageHelper;
import com.org.oracle.properties.GiteeProperties;
import com.org.oracle.strategy.FileStrategy;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author: heiye
 * @date: 2024/11/21 下午1:33
 * @version: v1.0.0
 * @description: TODO
 */
@Slf4j
public class GiteeFileStrategy implements FileStrategy {

    @Resource
    private GiteeProperties giteeProperties;

    // Gitee 新建文件链接
    public static final String GITTE_UPLOAD_IMG_BED = " https://gitee.com/api/v5/repos/%s/%s/contents/%s";

    @Resource
    private ImageHelper imageHelper;

    /**
     * 图片上传
     *
     * @param image
     * @param bucketName
     * @return
     */
    @Override
    @SneakyThrows
    public String uploadImg(MultipartFile image, String bucketName) {
        log.info("## 文件上传至 Gitee...");

        // 判断图片是否为空
        if (image == null || image.getSize() == 0) {
            log.error("==> 上传文件异常：图片大小为空 ...");
            throw new CustomException(ResponseCodeEnum.FILE_SIZE_EMPTY);
        }

        // 图片的原始名称
        String originalFileName = image.getOriginalFilename();
        // 获取图片的后缀，如 .jpg
        String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));

        if (!".jpg".equals(suffix) && !".jpeg".equals(suffix)) {
            throw new CustomException(ResponseCodeEnum.IMAGE_TYPE_ERROR);
        }

        // 尽可能压缩图片到 1 MB 以下
        MultipartFile compressedImage = imageHelper.compressImage(image);

        // 生成存储对象的名称（将 UUID 字符串中的 - 替换成空字符串）
        String key = UUID.randomUUID().toString().replace("-", "");

        // 拼接上文件后缀，即为要存储的文件名
        String objectName = String.format("%s%s", key, suffix);

        // 图片路径
        String url = null;
        // 传回的值为空，图片大小 小于 1 MB 直接上传图片
        if (Objects.isNull(compressedImage)) {
            // 上传图片到 Gitee
            url = uploadImgReq(image, objectName);

        } else {
            // 注意：此处无法异步上传图片，由于图床是 gitee 每次提交都是 push 一个分支
            // 如果异步进行，两次请求会拿到一样的分支，然后 push，在这个过程中 push 是有先后的
            // 可能原图先 push 进去了，但是压缩后的图片因为发现 push 的分支与一开始获得的分支产生了不一致
            // 导致压缩后的图片 push 失败，这里也涉及到了一个锁的问题了，为了防止该情况产生，只能同步上传了
            // 上传原图
            uploadImgReq(image, objectName);

            // 重新起名表明为压缩图片
            objectName = String.format("%s-compressed%s", key, suffix);

            // 上传压缩后的图片
            url = uploadImgReq(compressedImage, objectName);
        }
        return url;
    }

    /**
     * 发送请求到 Gitee 上传图片
     *
     * @param file
     * @return
     */
    @SneakyThrows
    private String uploadImgReq(MultipartFile file, String objectName) {
        log.info("==> 开始上传图片至 Gitee, ObjectName: {}", objectName);

        // 填充请求路径
        String request = String.format(GITTE_UPLOAD_IMG_BED,
                giteeProperties.getOwner(),
                giteeProperties.getRepo(),
                objectName);

        // 构建 body
        HashMap<String, Object> body = new HashMap<>();
        body.put("access_token", giteeProperties.getAccessToken());
        body.put("content", Base64.encode(file.getBytes()));
        body.put("message", "add img");

        // 发送请求
        String result = HttpUtil.post(request, body);

        // 处理请求结果
        JSONObject jsonObject = JSONUtil.parseObj(result);

        // 请求失败校验
        if (Objects.isNull(jsonObject.getObj("commit"))) {
            throw new CustomException(ResponseCodeEnum.IMAGE_UPLOAD_FAIL);
        }

        String url = (String) JSONUtil.parseObj(jsonObject.getObj("content"))
                .getObj("download_url");

        log.info("==> 上传图片至 Gitee 成功，访问路径: {}", url);

        // 返回图片地址
        return url;
    }
}
